#include <iostream>
#include <unistd.h>
#include <pthread.h>

using namespace std;

volatile bool quit = false; // quit不进行编译器优化，直接存取原始内存地址
typedef void (*func_t)(const string &name,
                       pthread_mutex_t *pmtx, pthread_cond_t *pcond);
#define TNUM 4

class ThreadData
{
public:
    ThreadData(const string &name, func_t func,
               pthread_mutex_t *pmtx, pthread_cond_t *pcond)
        : _name(name),
          _func(func),
          _pmtx(pmtx),
          _pcond(pcond)
    {
    }

public:
    string _name;
    func_t _func;
    pthread_mutex_t *_pmtx;
    pthread_cond_t *_pcond;
};

void func1(const string &name,
           pthread_mutex_t *pmtx, pthread_cond_t *pcond)
{
    while (!quit)
    {
        // wait作用的区域一定在加锁和解锁区间的
        pthread_mutex_lock(pmtx);
        // if () // 临界资源是否就绪

        // 默认该线程在执行时，wait到后，立即阻塞
        pthread_cond_wait(pcond, pmtx);
        cout << name << "running  " << endl;
        pthread_mutex_unlock(pmtx);
    }
}
void func2(const string &name,
           pthread_mutex_t *pmtx, pthread_cond_t *pcond)
{
    while (!quit)
    {
        pthread_mutex_lock(pmtx);

        // 默认该线程在执行时，wait到后，立即阻塞
        pthread_cond_wait(pcond, pmtx);
        cout << name << "running  " << endl;
        pthread_mutex_unlock(pmtx);
    }
}
void func3(const string &name,
           pthread_mutex_t *pmtx, pthread_cond_t *pcond)
{
    while (!quit)
    {
        pthread_mutex_lock(pmtx);

        // 默认该线程在执行时，wait到后，立即阻塞
        pthread_cond_wait(pcond, pmtx);
        cout << name << "running  " << endl;
        pthread_mutex_unlock(pmtx);
    }
}
void func4(const string &name,
           pthread_mutex_t *pmtx, pthread_cond_t *pcond)
{
    while (!quit)
    {
        pthread_mutex_lock(pmtx);

        // 默认该线程在执行时，wait到后，立即阻塞
        pthread_cond_wait(pcond, pmtx);
        cout << name << "running  " << endl;
        pthread_mutex_unlock(pmtx);
    }
}
void *Entry(void *args)
{
    ThreadData *td = (ThreadData *)args;
    td->_func(td->_name, td->_pmtx, td->_pcond);
    delete td;
    return nullptr;
}

int main()
{
    pthread_mutex_t mtx;
    pthread_cond_t cond;
    pthread_mutex_init(&mtx, nullptr);
    pthread_cond_init(&cond, nullptr);

    pthread_t tid[TNUM];
    func_t f[TNUM] = {func1, func2, func3, func4};
    for (int i = 0; i < TNUM; i++)
    {
        string name = "Thread";
        name += to_string(i + 1);
        ThreadData *td = new ThreadData(name, f[i], &mtx, &cond);
        pthread_create(tid + i, nullptr, Entry, (void *)td);
    }
    sleep(3);
    // 控制线程

    int cnt = 10;
    while (cnt)
    {
        cout << "thread resume run code......" << cnt-- << endl;
        pthread_cond_signal(&cond);
        // pthread_cond_broadcast(&cond);
        sleep(1);
    }
    cout << "ctrl done" << endl;
    quit = true;
    pthread_cond_broadcast(&cond);

    for (int i = 0; i < TNUM; i++)
    {
        pthread_join(tid[i], nullptr);

        cout << "thread: " << tid[i] << "  quit" << endl;
    }

    pthread_mutex_destroy(&mtx);
    pthread_cond_destroy(&cond);
}